package com.black.cat.jvm.rtda.heap.constantpool;

import com.black.cat.jvm.classfile.constantpool.ConstantInfo;
import com.black.cat.jvm.classfile.constantpool.ConstantPool;
import com.black.cat.jvm.classfile.constantpool.impl.*;
import com.black.cat.jvm.common.CommonValue;
import com.black.cat.jvm.rtda.heap.methodarea.JClass;


/**
 * @Author blackcat
 * @create 2021/8/14 10:47
 * @version: 1.0
 * @description:运行时常量池
 */
public class RunTimeConstantPool {
    private JClass clazz;

    private java.lang.Object[] constants;

    public RunTimeConstantPool(JClass clazz, ConstantPool constantPool) {
        int cpCount = constantPool.getConstantInfos().length;
        this.clazz = clazz;
        this.constants = new java.lang.Object[cpCount];

        ConstantInfo[] constantInfos = constantPool.getConstantInfos();
        for (int i = 1; i < cpCount; i++) {
            ConstantInfo constantInfo = constantInfos[i];

            switch (constantInfo.getTag()) {
                case CommonValue.CONSTANT_POOL_TAG_INTEGER:
                    ConstantInfoInteger integerInfo = (ConstantInfoInteger) constantInfo;
                    this.constants[i] = Integer.valueOf(integerInfo.getValue());
                    break;
                case CommonValue.CONSTANT_POOL_TAG_FLOAT:
                    ConstantInfoFloat floatInfo = (ConstantInfoFloat) constantInfo;
                    this.constants[i] = Float.valueOf(floatInfo.getValue());
                    break;
                case CommonValue.CONSTANT_POOL_TAG_LONG:
                    ConstantInfoLong longInfo = (ConstantInfoLong) constantInfo;
                    this.constants[i] = Long.valueOf(longInfo.getValue());
                    i++;
                    break;
                case CommonValue.CONSTANT_POOL_TAG_DOUBLE:
                    ConstantInfoDouble doubleInfo = (ConstantInfoDouble) constantInfo;
                    this.constants[i] = Double.valueOf(doubleInfo.getValue());
                    i++;
                    break;
                case CommonValue.CONSTANT_POOL_TAG_STRING:
                    ConstantInfoString stringInfo = (ConstantInfoString) constantInfo;
                    this.constants[i] = stringInfo.getValue();
                    break;
                case CommonValue.CONSTANT_POOL_TAG_CLASS:
                    ConstantInfoClass classInfo = (ConstantInfoClass) constantInfo;
                    this.constants[i] = ClassRef.newClassRef(this, classInfo);
                    break;
                case CommonValue.CONSTANT_POOL_TAG_FIELD_REF:
                    this.constants[i] = FieldRef.newFieldRef(this, (ConstantInfoFieldref) constantInfo);
                    break;
                case CommonValue.CONSTANT_POOL_TAG_INTERFACE_METHOD_REF:
                    this.constants[i] = InterfaceMethodRef.newInterfaceMethodRef(this, (ConstantInterfaceMethodRefInfo) constantInfo);
                    break;
                case CommonValue.CONSTANT_POOL_TAG_METHOD_REF:
                    this.constants[i] = MethodRef.newMethodRef(this, (ConstantInfoMethodref) constantInfo);
                    break;
                default:
            }
        }
    }

    public JClass getClazz() {
        return clazz;
    }

    public void setClazz(JClass clazz) {
        this.clazz = clazz;
    }

    public java.lang.Object getConstants(int idx) {
        return constants[idx];
    }
}
